package conn

import (
	"gitee.com/cooge/impush/core"
	"gitee.com/cooge/impush/message"
	"gitee.com/cooge/impush/stream"
	"gitee.com/cooge/impush/user"
	log "github.com/sirupsen/logrus"
	"golang.org/x/net/websocket"
	"strconv"
	"time"
	"gitee.com/cooge/impush/util"
	"sync"
)

type WsConn struct {
	*user.UserLite
	ms *stream.MessageStream
	closeOnce sync.Once
}

func NewWsConn(conn *websocket.Conn) *WsConn {
	return &WsConn{UserLite:user.NewUserLite(conn, 30000, conn.Request().FormValue("id"),util.GetNowTime(),message.WEBSOCKET,true), ms:stream.NewMessageStream(conn)}
}
func (ws *WsConn) Start() {
	if len(ws.UserId) == 0 {
		ws.Write(message.StartLogin())
	} else {
		ws.SetReadDeadline()
		core.AddUser(ws.UserId, ws)
	}
	for {
		msg, err := ws.ms.ReadMessage()
		if err != nil {
			log.Debug(ws.UserId, "断开连接", err)
			break
		}
		ws.handle(msg)

	}
	ws.Close(ws.UserId)
}
func (ws *WsConn) Close(userId string) error {
	ws.closeOnce.Do(func() {
		core.DeleteUser(userId, ws)
		ws.UserTCPConn.Close()
	})
	return nil
}

func (ws *WsConn) GetUser() string {
	return ws.RemoteAddr().String()
}
func (ws *WsConn) SendMessage(msg *message.Message) (int, error) {
	bs := msg.MessageToByte()
	return ws.Write(bs)
}

func (ws *WsConn) SetReadDeadline() {
	ws.UserTCPConn.SetReadDeadline(time.Now().Add(time.Duration(ws.LiveTime) * time.Millisecond))
}

func (ws *WsConn) handle(msg *message.Message) {
	type_ := msg.Heads.Get(message.TYPE)
	switch type_ {
	case message.LOGIN:
		{
			usarename := msg.Heads.Get(message.USERNAME)
			if len(usarename) > 0 {
				time_ := msg.Heads.Get(message.TIME)
				if len(time_) > 0 {
					ti, err := strconv.Atoi(time_)
					if err == nil {
						ws.LiveTime = ti + ti + ws.LiveTime
					} else {
						log.Debug("获取心跳时间失败", err)
					}
				}
			}
			core.AddUser(usarename, ws)
			ws.UserId = usarename
			ws.Write(message.LoginSuccess())
		}
	case message.MESSAGE:
		{
			touser := msg.Heads.Get(message.TO)
			msg.Heads[message.FROM] = ws.UserId
			_, err := core.SendMessage(touser, msg)
			if err == nil {
				ws.SendMessage(message.SendSuccess(msg.Heads[message.MESSAGE_ID]))
			} else {
				ws.SendMessage(message.SendFail(msg.Heads[message.MESSAGE_ID]))
			}
		}
	case message.LIVE:
		{
			ws.Write(message.Live())
		}
	}
	ws.SetReadDeadline()
}
